package com.galaxy.util;

import com.drew.imaging.jpeg.JpegMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifDirectoryBase;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;

/**
 * Created by 李新宇
 * 2019-05-17 11:33
 */
public class RotateImageUtil {

    // 处理ios图片旋转的问题
    public static InputStream getPictureByInputStream(InputStream in, String suffix) throws IOException {

        //获取最后一个.的位置
        int lastIndexOf = suffix.lastIndexOf(".");
        //获取文件的后缀名 .jpg
        if (lastIndexOf != -1) suffix = suffix.substring(lastIndexOf + 1);

        //name为前端请求图片名，如 a.jpg
        byte[] bytes = cloneIn(in);
        BufferedImage src = ImageIO.read(new ByteArrayInputStream(bytes));
        BufferedImage bi = null;
        //图片存在
        if (src != null) {
            //获取图片旋转角度
            int angel = getRotateAngleForPhoto(new ByteArrayInputStream(bytes));
            //图片被翻转，调整图片
            if (angel != 0) {
                int src_width = src.getWidth(null);
                int src_height = src.getHeight(null);
                Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(src_width, src_height)), angel);

                bi = new BufferedImage(rect_des.width, rect_des.height, BufferedImage.TYPE_INT_RGB);
                Graphics2D g2 = bi.createGraphics();

                // transform(这里先平移、再旋转比较方便处理；绘图时会采用这些变化，绘图默认从画布的左上顶点开始绘画，源图片的左上顶点与画布左上顶点对齐，然后开始绘画，修改坐标原点后，绘画对应的画布起始点改变，起到平移的效果；然后旋转图片即可)
                //平移（原理修改坐标系原点，绘图起点变了，起到了平移的效果，如果作用于旋转，则为旋转中心点）
                g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);

                //旋转（原理translate(dx,dy)->rotate(radians)->translate(-dx,-dy);修改坐标系原点后，旋转90度，然后再还原坐标系原点为(0,0),但是整个坐标系已经旋转了相应的度数 ）
                g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);

                g2.drawImage(src, null, null);

                ByteArrayInputStream byteArrayInputStream = bufferedImageToInputStream(bi, suffix);

                return byteArrayInputStream;
            }
        } else {
            //图片不存在
            System.out.println("图片不存在");

        }

        return new ByteArrayInputStream(bytes);


    }


    /**
     * 读取指定图片
     */
    public static BufferedImage getPicture(String path) {
        BufferedImage bi = null;
        try {
            File file = new File(path);
            if (!file.exists()) {
                return null;
            }
            bi = ImageIO.read(file);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bi;
    }


    /**
     * 图片翻转时，计算图片翻转到正常显示需旋转角度
     */
    public static int getRotateAngleForPhoto(InputStream in) {
//        File file = new File(fileName);
        int angel = 0;
        Metadata metadata;
        try {

            metadata = JpegMetadataReader.readMetadata(in);
            Directory directory = metadata.getFirstDirectoryOfType(ExifDirectoryBase.class);
            if (directory != null && directory.containsTag(ExifDirectoryBase.TAG_ORIENTATION)) {
                // Exif信息中方向　　
                int orientation = directory.getInt(ExifDirectoryBase.TAG_ORIENTATION);
                // 原图片的方向信息
                if (6 == orientation) {
                    //6旋转90
                    angel = 90;
                } else if (3 == orientation) {
                    //3旋转180
                    angel = 180;
                } else if (8 == orientation) {
                    //8旋转90
                    angel = 270;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("图片旋转角度：" + angel);
        return angel;
    }


    /**
     * 计算旋转参数
     */
    public static Rectangle CalcRotatedSize(Rectangle src, int angel) {
        // if angel is greater than 90 degree,we need to do some conversion.
        if (angel >= 90) {
            if (angel / 90 % 2 == 1) {
                int temp = src.height;
                src.height = src.width;
                src.width = temp;
            }
            angel = angel % 90;
        }

        double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
        double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
        double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
        double angel_data_width = Math.atan((double) src.height / src.width);
        double angel_data_height = Math.atan((double) src.width / src.height);

        int len_data_width = (int) (len * Math.cos(Math.PI - angel_alpha - angel_data_width));
        int len_data_height = (int) (len * Math.cos(Math.PI - angel_alpha - angel_data_height));
        int des_width = src.width + len_data_width * 2;
        int des_height = src.height + len_data_height * 2;
        return new java.awt.Rectangle(new Dimension(des_width, des_height));
    }

    /**
     * 将BufferedImage转换为InputStream
     *
     * @param image
     * @return
     */
    public static ByteArrayInputStream bufferedImageToInputStream(BufferedImage image, String x) {
        ByteArrayOutputStream os = new ByteArrayOutputStream();

        try {
            ImageIO.write(image, x, os);
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(os.toByteArray());
            return byteArrayInputStream;
        } catch (IOException e) {
            System.out.println(e);
        }
        return null;
    }

    public static byte[] cloneIn(InputStream in) throws IOException {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = in.read(buffer)) > -1) {
            baos.write(buffer, 0, len);
        }
        baos.flush();

        byte[] bytes = baos.toByteArray();

        return bytes;
    }

    public static void main(String[] args) throws IOException {
        String filePath = "C:/Users/48987/Desktop/1.png";

        //获取最后一个.的位置
        int lastIndexOf = filePath.lastIndexOf(".");
        //获取文件的后缀名 .jpg
        String suffix = filePath.substring(lastIndexOf + 1);

        System.out.println(suffix);

        FileInputStream fileInputStream = new FileInputStream(filePath);


        InputStream pictureByName = getPictureByInputStream(fileInputStream, suffix);

        FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\48987\\Desktop\\2.png");


        byte[] buf = new byte[1024];
        int length = 0;
        //循环读取文件内容，输入流中将最多buf.length个字节的数据读入一个buf数组中,返回类型是读取到的字节数。
        //当文件读取到结尾时返回 -1,循环结束。
        while ((length = pictureByName.read(buf)) != -1) {
            fileOutputStream.write(buf, 0, length);
        }


    }
}
